{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. MetaClass"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "4.1 Python 底层语言设计层面是如何实现 metaclass 的\n",
    "\n",
    "- 第一，所有的 Python 的用户定义类，都是 type 这个类的实例。\n",
    "- 第二，用户自定义类，只不过是 type 类的__call__运算符重载。\n",
    "- 第三，metaclass 是 type 的子类，通过替换 type 的__call__运算符重载机制，“超越变形”正常的类。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class '__main__.MyClass'>\n",
      "<class 'type'>\n"
     ]
    }
   ],
   "source": [
    "# Python 3和Python 2类似\n",
    "class MyClass:\n",
    "  pass\n",
    "\n",
    "instance = MyClass()\n",
    "\n",
    "print(type(instance))\n",
    "# 输出\n",
    "\n",
    "\n",
    "print(type(MyClass))\n",
    "# 输出\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "\n",
    "class MyClass:\n",
    "  data = 1\n",
    "\n",
    "# 真正执行\n",
    "\n",
    "class = type(classname, superclasses, attributedict)\n",
    "\n",
    "# 这里等号右边的type(classname, superclasses, attributedict)，就是 type 的__call__运算符重载，它会进一步调用\n",
    "type.__new__(typeclass, classname, superclasses, attributedict)\n",
    "type.__init__(class, classname, superclasses, attributedict)\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class '__main__.MyClass'> <__main__.MyClass object at 0x0000018746CF1B80>\n",
      "1\n",
      "<class '__main__.MyClass'> <__main__.MyClass object at 0x0000018746CF00E0>\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "class MyClass:\n",
    "  data = 1\n",
    "  \n",
    "instance = MyClass()\n",
    "print(MyClass, instance)\n",
    "# 输出\n",
    "\n",
    "print(instance.data)\n",
    "# 输出\n",
    "\n",
    "\n",
    "MyClass = type('MyClass', (), {'data': 1})\n",
    "instance = MyClass()\n",
    "print(MyClass, instance)\n",
    "# 输出\n",
    "\n",
    "\n",
    "print(instance.data)\n",
    "# 输出\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "===>Mymeta.__new__\n",
      "Mymeta\n",
      "===>Mymeta.__init__\n",
      "Foo\n",
      "{'__module__': '__main__', '__qualname__': 'Foo', 'yaml_tag': '!Foo', '__init__': <function Foo.__init__ at 0x0000018746D3CAE0>, '__new__': <function Foo.__new__ at 0x0000018746D3E480>}\n",
      "!Foo\n",
      "===>Mymeta.__call__\n",
      "Foo.__new__\n",
      "Foo.__init__\n"
     ]
    }
   ],
   "source": [
    "class Mymeta(type):\n",
    "    def __init__(self, name, bases, dic):\n",
    "        super().__init__(name, bases, dic)\n",
    "        print('===>Mymeta.__init__')\n",
    "        print(self.__name__)\n",
    "        print(dic)\n",
    "        print(self.yaml_tag)\n",
    "\n",
    "    def __new__(cls, *args, **kwargs):\n",
    "        print('===>Mymeta.__new__')\n",
    "        print(cls.__name__)\n",
    "        return type.__new__(cls, *args, **kwargs)\n",
    "\n",
    "    def __call__(cls, *args, **kwargs):\n",
    "        print('===>Mymeta.__call__')\n",
    "        obj = cls.__new__(cls)\n",
    "        cls.__init__(cls, *args, **kwargs)\n",
    "        return obj\n",
    "    \n",
    "class Foo(metaclass=Mymeta):\n",
    "    yaml_tag = '!Foo'\n",
    "\n",
    "    def __init__(self, name):\n",
    "        print('Foo.__init__')\n",
    "        self.name = name\n",
    "\n",
    "    def __new__(cls, *args, **kwargs):\n",
    "        print('Foo.__new__')\n",
    "        return object.__new__(cls)\n",
    "\n",
    "foo = Foo('foo')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
